package org.mijia.dotsbox.rcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.mijia.dotsbox.core.model.Folder;
import org.mijia.dotsbox.utils.LogUtils;
import org.mijia.dotsbox.utils.RegexUtils;

public class NewChannelDialog extends TitleAreaDialog {

    private static final int DIALOG_MIN_WIDTH = 350;
    private Button btnOk;
    private Combo dotsType;
    private Text input;
    private Label inputLabel;
    private String titleInput;
    
    private static class DotsTypeInfor {
        private String format;
        private String title;
        private String description;
        private String label;
        private String encode;
        
        DotsTypeInfor(String f, String t, String desc, String label, String encode) {
            format = f;
            title = t;
            description = desc;
            this.label = label;
            this.encode = encode;
        }
        
        String getDotsUrl(String input) {
            String eurl;
            if (encode.equals("None")) {
                eurl = input;
            } else {
                try {
                    eurl = URLEncoder.encode(input, encode);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    eurl = input;
                }
            }
            return String.format(format, eurl);
        }
        
        String getDotsLabel(String input) {
            return String.format(label, input);
        }
    }
    
    private List<DotsTypeInfor> dotsTypeInfoList = new ArrayList<DotsTypeInfor>();
    private DotsTypeInfor currentDotsType = null;
    
    private final Folder cf;
    private final ChannelTreeModel treeModel;
    
    public NewChannelDialog(Folder folder, Shell parentShell, ChannelTreeModel model) {
        super(parentShell);
        cf = folder;
        treeModel = model;
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginWidth = 5;
        layout.marginHeight = 10;
        layout.verticalSpacing = 5;
        composite.setLayout(layout);
        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
        composite.setLayoutData(gd);
        
        setMessage("Please input necessary info for the channel",
                IMessageProvider.INFORMATION);

        Label label = new Label(composite, SWT.NONE);
        label.setText("Dots Type: ");
        gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
        label.setLayoutData(gd);
        
        dotsType = new Combo(composite, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
        gd = new GridData(GridData.FILL_HORIZONTAL);
        dotsType.setLayoutData(gd);
        
        inputLabel = new Label(composite, SWT.NONE);
        gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
        inputLabel.setLayoutData(gd);
        
        input = new Text(composite, SWT.BORDER | SWT.SINGLE);
        gd = new GridData(GridData.FILL_HORIZONTAL);
        input.setLayoutData(gd);
        input.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                verifyInput();
            }
        });

        loadDotsObjectType();
        dotsType.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                int nSelect = dotsType.getSelectionIndex();
                if (nSelect >= 0 && nSelect < dotsTypeInfoList.size()) {
                    currentDotsType = dotsTypeInfoList.get(nSelect);
                    inputLabel.setText(currentDotsType.title + ": ");
                    inputLabel.getParent().layout(true);
                }
            }
        });
        
        input.setFocus();
        
        return super.createDialogArea(parent);
    }

    private void loadDotsObjectType() {
        DotsTypeInfor feeds = new DotsTypeInfor("%s", "Feed Link", "RSS/RDF/Atom News Feed", "%s", "None");
        dotsTypeInfoList.add(feeds);
        dotsType.add(feeds.description);
        inputLabel.setText(feeds.title + ": ");
        currentDotsType = feeds;
        dotsType.select(0);
        
        // load from .properties file
        Properties newsProperties = new Properties();
        InputStream is = NewChannelDialog.class.getResourceAsStream("news.properties");
        if (is == null) {
            LogUtils.info("The news.properties file not exists!");
            return;
        }
        
        try {
            newsProperties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
            LogUtils.error("Cannot load news.properties: " + e.getMessage());
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        int dotsTypeCount = Integer.parseInt(newsProperties.getProperty("news.dotstype.count", "0"));
        for (int i = 0; i < dotsTypeCount; ++i) {
            String prefix = "news.dotstype_" + (i + 1) + ".";
            String format = newsProperties.getProperty(prefix + "format", "");
            String title  = newsProperties.getProperty(prefix + "title", "");
            String desc = newsProperties.getProperty(prefix + "description", "");
            String label = newsProperties.getProperty(prefix + "label", "");
            String encode = newsProperties.getProperty(prefix + "encode", "");
            
            DotsTypeInfor infor = new DotsTypeInfor(format, title, desc, label, encode);
            dotsTypeInfoList.add(infor);
            dotsType.add(infor.description);
        }
    }
    
    private void verifyInput() {
        titleInput = input.getText().trim();
        if(titleInput == null || titleInput.length() == 0) {
            titleInput = "";
            btnOk.setEnabled(false);
        } else {
            String key = getInputUrl();
            if (treeModel.containsChannel(key)) {
                setMessage("We already have a channel with \"" + titleInput + "\"",
                        IMessageProvider.ERROR);
                btnOk.setEnabled(false);
                return;
            }
            
            int nSelect = dotsType.getSelectionIndex();
            if (nSelect == 0 && !RegexUtils.isValidURL(key)) {
                setMessage("This is not a valid URL \"" + titleInput + "\"",
                        IMessageProvider.ERROR);
                btnOk.setEnabled(false);
                return;
            }
            
            setMessage("Please input necessary info for the channel: ",
                    IMessageProvider.INFORMATION);
            btnOk.setEnabled(true);
        }
    }
    
    public String getInputUrl() {
        return currentDotsType.getDotsUrl(titleInput);
    }
    
    public String getInputLabel() {
        return currentDotsType.getDotsLabel(titleInput);
    }
    
    @Override
    protected void configureShell(Shell newShell) {
        super.configureShell(newShell);
        String foldername = cf != null ? cf.getName() : "All News";
        newShell.setText("New Channel for [ " + foldername + " ]");
    }

    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        btnOk = createButton(parent, IDialogConstants.OK_ID, "&Ok", true);
        btnOk.setEnabled(false);
        Button btnCancel = createButton(parent, IDialogConstants.CANCEL_ID, "&Cancel", false);
    }

    @Override
    protected int getShellStyle() {
        int style = SWT.TITLE | SWT.APPLICATION_MODAL | SWT.BORDER | SWT.CLOSE | getDefaultOrientation();
        return style;
    }
    
    @Override
    protected void initializeBounds() {
        super.initializeBounds();
        Point bestSize = getShell().computeSize(
                convertHorizontalDLUsToPixels(DIALOG_MIN_WIDTH), SWT.DEFAULT);
        Point location = getInitialLocation(bestSize);
        getShell().setBounds(location.x, location.y, bestSize.x, bestSize.y);
    }

    @Override
    protected void setButtonLayoutData(Button button) {
        GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
        gd.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT,
                SWT.DEFAULT, true).x);
        button.setLayoutData(gd);
    }
}
